<!DOCTYPE HTML>
<html>

<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="utf-8">
  
  <title>在.net core中使用配置文件的几个示例和方法 | DeepThought</title>
  <meta name="google-site-verification" content="Ei6mmDdf-cJwox1RvJOeX8Dc720fqWjZQu-Ww2BjBt4">
  
  <meta name="author" content="积慕">
  
  <meta name="description" content=".net,dotnet,core,dotnet core,.netcore,.net core,windows服务,windows 服务,windows service,configuration,configuration builder,配置,配置文件,.NET CORE 配置文件,.NET6 configuration, .NET6 没有 startup.cs, program 中使用configuration">
  
  
  <meta name="keywords" content=".net,dotnet,core,dotnet core,.netcore,.net core,windows服务,windows 服务,windows service,configuration,configuration builder,配置,配置文件,.NET CORE 配置文件,.NET6 configuration, .NET6 没有 startup.cs, program 中使用configuration">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

  
  <meta property="og:title" content="在.net core中使用配置文件的几个示例和方法">
  <meta property="og:site_name" content="DeepThought">

  
  <meta property="og:image" content>
  

  <link href="https://pic.zhuliang.ltd/favicon.ico" rel="shortcut icon" type="image/x-icon">
  <link rel="alternate" href="/atom.xml" title="DeepThought" type="application/atom+xml">
  <link rel="stylesheet" href="/css/style.css" media="screen" type="text/css">

  <link rel="stylesheet" href="//at.alicdn.com/t/font_1187293_8fec2ou5fyx.css">

  <!-- <link rel="stylesheet" href="//cdn.bootcss.com/highlight.js/9.6.0/styles/github.min.css"> -->
  <!-- <script src="//cdn.bootcss.com/highlight.js/9.6.0/highlight.min.js"></script> -->
  <script src="/js/highlight.min.js"></script>

  <link rel="stylesheet" href="/css/markdown.css">

  <script src="/js/av-min.3.0.4.js"></script>
  <script src="/js/Valine.min.1.3.6.js"></script>

</head></html>

<body>
  <header id="header" class="inner"><div class="alignleft">
  <h1><a href="/">DeepThought</a></h1>
  <h2><a href="/">知识需沉淀，更需分享</a></h2>
</div>
<nav id="main-nav" class="alignright">
  <ul>
    
      <li><a href="/">首页</a></li>
    
      <li><a href="/about">关于我</a></li>
    
      <li><a href="/atom.xml">订阅RSS</a></li>
    
  </ul>
  <div class="clearfix"></div>
</nav>
<div class="clearfix"></div>
        </header>
  <div id="content" class="inner">
    <div id="main-col" class="alignleft"><div id="wrapper"><article class="post">
  
  <div class="post-content">
    <header>
      
        <div class="icon"></div>
      

 
      
  
    <h1 class="title">在.net core中使用配置文件的几个示例和方法</h1>
  


      
        <time datetime="2019-02-17T16:27:53.000Z">
          create: 2019-02-18 00:27:53 | update: 2023-07-17 19:20:53
            <span style="float: right;">
    <span class="post-count" id="busuanzi_container_page_pv" style="display: inline;">
        
        本文总阅读量: <span id="busuanzi_value_page_pv"></span>&nbsp;次
        <span class="blueSeparate">&nbsp;|&nbsp;</span>
        
        <span class="post-count">文章总字数:&nbsp;2.6k&nbsp;字</span>
    <span class="blueSeparate">&nbsp;|&nbsp;</span>
    <span class="post-count">阅读约需:&nbsp;13&nbsp;分钟</span>
    <br>
</span>
</span>
        </time>
      
            
    </header>
    <div class="entry">
      
      <blockquote>
<p>本文基于 .net core 2.2（更新.NET6 示例）</p>
<p>主要包含的示例：</p>
<ul>
<li>通过DI进行使用配置文件<ul>
<li>如何在 ASP.NET 中使用配置文件</li>
</ul>
</li>
<li>直接硬编码使用配置文件<ul>
<li>如何在控制台中使用配置文件</li>
</ul>
</li>
</ul>
</blockquote>
<h1 id="示例：ASP-NET-MVC"><a href="#示例：ASP-NET-MVC" class="headerlink" title="示例：ASP.NET MVC"></a>示例：ASP.NET MVC</h1><blockquote>
<p>asp.net mvc已经内部实现了对配置appsettings.json文件的使用，builder默认支持热更新。</p>
</blockquote>
<h2 id="使用示例："><a href="#使用示例：" class="headerlink" title="使用示例："></a>使用示例：</h2><p>假设appsettings.json内容为：</p>
<p></p><p class="code-caption" data-lang="json" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="json">{
  &quot;Logging&quot;: {
    &quot;LogLevel&quot;: {
      &quot;Default&quot;: &quot;Warning&quot;
    }
  },
  &quot;AllowedHosts&quot;: &quot;*&quot;
}
</code></pre>
<ol>
<li><p>新建一个跟appsettings.json结构保持一致的类，如：</p>
<a id="more"></a>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">namespace webapp.Models
{
 public class AppsettingsModel
 {
     public Logging Logging { get; set; }

     public string AllowedHosts { get; set; }
 }

 public class Logging
 {
     public LogLevel LogLevel { get; set; }
 }

 public class LogLevel
 {
     public string Default { get; set; }
 }
}
</code></pre>
</li>
</ol>
<blockquote>
<p>PS：</p>
<ul>
<li><p>需要注意，用于IOptions或者IOptionsSnapshot中的模型的各个属性，其setter必须是公共的，不能是私有。</p>
</li>
<li><p>另外对于该模型，必须要有一个无参构造函数。</p>
</li>
</ul>
</blockquote>
<ol start="2">
<li><p>在Startup.cs中进行依赖注入<br></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">public void ConfigureServices(IServiceCollection services)
{
 services.Configure&lt;CookiePolicyOptions&gt;(options =&gt;
 {
     options.CheckConsentNeeded = context =&gt; true;
     options.MinimumSameSitePolicy = SameSiteMode.None;
 });
 // 依赖注入
 services.Configure&lt;AppsettingsModel&gt;(Configuration);
 services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
</code></pre>
</li>
<li><p>在controller中调用：</p>
</li>
</ol>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">public class TestController : Controller
{
    private readonly AppsettingsModel _appsettingsModel;
    //若要使用热更新，则入参调整为 IOptionsSnapshot&lt;T&gt;
    public TestController(IOptions&lt;AppsettingsModel&gt; appsettingsModel)
    {
        _appsettingsModel = appsettingsModel.Value;
    }

    public IActionResult Index()
    {
        return View(&quot;Index&quot;, _appsettingsModel.Logging.LogLevel.Default);
    }
}
</code></pre>
<ul>
<li>这里需要注意一点，DI时，如果是单例，则无法使用是IOptionsSnapshot，会报错。</li>
</ul>
<h2 id="如何覆写默认行为？如取消热更新支持，方法如下："><a href="#如何覆写默认行为？如取消热更新支持，方法如下：" class="headerlink" title="如何覆写默认行为？如取消热更新支持，方法如下："></a>如何覆写默认行为？如取消热更新支持，方法如下：</h2><p>假设测试controller为</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">public class TestController : Controller
{
    private readonly AppsettingsModel _appsettingsModel;
    //使用的是：IOptionsSnapshot&lt;T&gt;
    public TestController(IOptionsSnapshot&lt;AppsettingsModel&gt; appsettingsModel)
    {
        _appsettingsModel = appsettingsModel.Value;
    }

    public IActionResult Index()
    {
        return View(&quot;Index&quot;, _appsettingsModel.Logging.LogLevel.Default);
    }
}
</code></pre>
<p>Program.cs</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =&gt;
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((context, config) =&gt; //1.通过该方法来覆盖配置
            {
                //2.重新添加json配置文件
                config.AddJsonFile(&quot;appsettings.json&quot;, false, false); //3.最后一个参数就是是否热更新的布尔值
            })
            .UseStartup&lt;Startup&gt;();
}
</code></pre>
<p><img src="http://pic.zhuliang.ltd/853140e9-c2ae-448b-9564-59e27023f387.png" alt="853140e9-c2ae-448b-9564-59e27023f387.png"></p>
<ul>
<li>这个时候，人为将热更新给关闭了，此时更新json文件后，修改后的内容不会更新到系统中。</li>
</ul>
<h1 id="示例：控制台"><a href="#示例：控制台" class="headerlink" title="示例：控制台"></a>示例：控制台</h1><blockquote>
<p>对于console项目，默认是没有这个dll的，需要自行从nuget安装</p>
<p>从nuget中安装：Microsoft.AspNetCore.All   （注意，末尾不是dll，而是all）</p>
<p>在项目中引入：Microsoft.Extensions.Configuration; 并使用ConfigurationBuilder来构建配置。</p>
</blockquote>
<h2 id="使用应用程序参数"><a href="#使用应用程序参数" class="headerlink" title="使用应用程序参数"></a>使用应用程序参数</h2><p>在控制台项目属性中增加name和class参数：</p>
<p><img src="http://pic.zhuliang.ltd/e4c2f50f-6d3d-4867-b12e-e2a3ede38da9.png" alt="e4c2f50f-6d3d-4867-b12e-e2a3ede38da9.png"></p>
<p>使用：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">class Program
{
    static void Main(string[] args)
    {
        var builder = new ConfigurationBuilder()
            .AddCommandLine(args);
        var configuration = builder.Build();

        Console.WriteLine($&quot;name:{configuration[&quot;name&quot;]}&quot;); //name:CLS
        Console.WriteLine($&quot;class:{configuration[&quot;class&quot;]}&quot;);   //class:Class_A

        Console.Read();
    }
}
</code></pre>
<h2 id="使用键值对枚举（这里以字典来说明）"><a href="#使用键值对枚举（这里以字典来说明）" class="headerlink" title="使用键值对枚举（这里以字典来说明）"></a>使用键值对枚举（这里以字典来说明）</h2><p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">class Program
{
            static void Main(string[] args)
            {
                var dict = new Dictionary&lt;string, string&gt;
                {
                    {&quot;name&quot;,&quot;MC&quot;},
                    {&quot;class&quot;,&quot;CLASS_MC&quot;}
                };
                var builder = new ConfigurationBuilder()
//                .AddCommandLine(args)
                .AddInMemoryCollection(dict);

                var configuration = builder.Build();

                Console.WriteLine($&quot;name:{configuration[&quot;name&quot;]}&quot;);//name:MC
                Console.WriteLine($&quot;class:{configuration[&quot;class&quot;]}&quot;);  //class:CLASS_MC

                Console.Read();
            }
}
</code></pre>
<p>注意事项：</p>
<ul>
<li>这里需要注意下，虽然 AddCommandLine 和 AddInMemoryCollection 可以同时调用，但不同的使用次序，效果是不一样的（后一个会覆盖前一个的内容—浅覆盖），如：</li>
</ul>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">/*
   假设 在项目属性中，定义的内容为：name=CLS，class=CLASS_CLS，grade=&quot;mygrade&quot;
   在代码中，dict的内容为：name=MC，class=CLASS_MC
*/
//对于代码：
varbuilder = new ConfigurationBuilder()
                   .AddCommandLine(args)
                   .AddInMemoryCollection(dict);
                   var configuration = builder.Build();

                   Console.WriteLine($&quot;name:{configuration[&quot;name&quot;]}&quot;);//name:MC
                   Console.WriteLine($&quot;class:{configuration[&quot;class&quot;]}&quot;);  //class:CLASS_MC
                   Console.WriteLine($&quot;grade:{configuration[&quot;grade&quot;]}&quot;);  //grade:mygrade

//对于代码：
varbuilder = new ConfigurationBuilder()                    
                   .AddInMemoryCollection(dict)
                   .AddCommandLine(args);
                   var configuration = builder.Build();

                   Console.WriteLine($&quot;name:{configuration[&quot;name&quot;]}&quot;);//name:CLS
                   Console.WriteLine($&quot;class:{configuration[&quot;class&quot;]}&quot;);  //class:CLASS_CLS
                   Console.WriteLine($&quot;grade:{configuration[&quot;grade&quot;]}&quot;);  //grade:mygrade
</code></pre>
<ul>
<li>另外，需要注意，如果用dotnet命令来执行CommandLineSample.dll，那么“应用程序参数”需要直接跟在命令的后面，如：<ul>
<li>另外如果AddInMemoryCollection和AddCommandLine同时使用，那么需要将AddCommandLine最后调用，否则一旦被覆盖了，再用dotnet来调用，会没有效果。<br><p class="code-caption" data-lang="sh" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><pre><code class="sh">dotnet   CommandLineSample.dll   name=111 class=222  grade=&quot;my grade&quot;
</code></pre>
</li>
</ul>
</li>
</ul>
<h2 id="使用JSON文件"><a href="#使用JSON文件" class="headerlink" title="使用JSON文件"></a>使用JSON文件</h2><ul>
<li>在项目根目录创建“jsconfig1.json”，同时修改该文件的属性：<ul>
<li>复制到输出目录：始终复制</li>
<li>生成操作：内容</li>
</ul>
</li>
</ul>
<p>JSON文件内容：</p>
<p></p><p class="code-caption" data-lang="json" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="json">{
      &quot;Class&quot;: &quot;Class A&quot;,
      &quot;PersonInfo&quot;: {
            &quot;name&quot;: &quot;my name&quot;,
            &quot;age&quot;: &quot;12&quot;
      },
      &quot;Hobbies&quot;: [
            {
                  &quot;Type&quot;: &quot;Family&quot;,
                  &quot;HobbyName&quot;: &quot;Piano&quot;
            },
            {
                  &quot;Type&quot;: &quot;Personal&quot;,
                  &quot;HobbyName&quot;: &quot;Singing&quot;
            }
      ]
}
</code></pre>
<p>代码：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">static void Main(string[] args)
{
    var builder = new ConfigurationBuilder()
        .AddJsonFile(&quot;jsconfig1.json&quot;);

    var configuration = builder.Build();

    Console.WriteLine($&quot;name:{configuration[&quot;PersonInfo:name&quot;]}&quot;);
    Console.WriteLine($&quot;class:{configuration[&quot;class&quot;]}&quot;);
    Console.WriteLine($&quot;age:{configuration[&quot;PersonInfo:age&quot;]}&quot;);
    //注意下调用参数时的格式：&quot;{参数Key}:{数组索引}:{子项参数Key}&quot;
    Console.WriteLine($&quot;FamilyHobby:{configuration[&quot;Hobbies:0:HobbyName&quot;]}&quot;);
    Console.WriteLine($&quot;PersonalHobby:{configuration[&quot;Hobbies:1:HobbyName&quot;]}&quot;);
    /* 也可以用模型的方式，如下：
    var settings = configuration.GetSection(&quot;RedisSettings&quot;).Get&lt;RedisSettings&gt;();
    */
    Console.Read();
}
</code></pre>
<h1 id="注册配置文件中的某一个段到一个class模型中"><a href="#注册配置文件中的某一个段到一个class模型中" class="headerlink" title="注册配置文件中的某一个段到一个class模型中"></a>注册配置文件中的某一个段到一个class模型中</h1><p>引用上面的json：</p>
<p></p><p class="code-caption" data-lang="json" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="json">{
      &quot;Class&quot;: &quot;Class A&quot;,
      &quot;PersonInfo&quot;: {
            &quot;name&quot;: &quot;my name&quot;,
            &quot;age&quot;: &quot;12&quot;
      },
      &quot;Hobbies&quot;: [
            {
                  &quot;Type&quot;: &quot;Family&quot;,
                  &quot;HobbyName&quot;: &quot;Piano&quot;
            },
            {
                  &quot;Type&quot;: &quot;Personal&quot;,
                  &quot;HobbyName&quot;: &quot;Singing&quot;
            }
      ]
}
</code></pre>
<p>如何在注册的时候希望将PersonInfo这个section单独注入到 PersonInfo.cs类中？（以mvc为例）</p>
<ul>
<li>PersonInfo.cs</li>
</ul>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">public class PersonInfo
{
    public string Name {get;set;}
    public int Age{get;set;}
}
</code></pre>
<ul>
<li>Startup.cs</li>
</ul>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure&lt;CookiePolicyOptions&gt;(options =&gt;
            {
                options.CheckConsentNeeded = context =&gt; true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            // 依赖注入
            services.Configure&lt;PersonInfo&gt;(Configuration.GetSection(&quot;PersonInfo&quot;));

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }
</code></pre>
<ul>
<li>在controller中使用：</li>
</ul>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">public class TestController : Controller
{
    private readonly PersonInfo   _personInfo;
    public TestController(IOptions&lt;PersonInfo&gt; personInfo)
    {
        _personInfo = _personInfo.Value;
    }

    public IActionResult Index()
    {
        return View(&quot;Index&quot;, _personInfo.Name);
    }
}
</code></pre>
<ul>
<li>在 startup.cs中使用</li>
</ul>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">//jwt           
services.Configure&lt;JwtSettings&gt;(Configuration.GetSection(&quot;JwtSettings&quot;));

var jwtSettings = new JwtSettings();
Configuration.Bind(&quot;JwtSettings&quot;, jwtSettings);
services.AddSanbenTechJwtService(jwtSettings.Issuer, jwtSettings.Audience);
</code></pre>
<h1 id="示例：在单元测试中使用-配置文件"><a href="#示例：在单元测试中使用-配置文件" class="headerlink" title="示例：在单元测试中使用 配置文件"></a>示例：在单元测试中使用 配置文件</h1><p>首先确保配置文件的属性：</p>
<p><img src="http://pic.zhuliang.ltd/014585b6-5c84-4949-b073-5ad83387fc72.png" alt></p>
<p>nuget安装、引入必要的库：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">Microsoft.Extensions.Configuration
Microsoft.Extensions.Configuration.Binder
Microsoft.Extensions.Configuration.Json
</code></pre>
<p>在构造函数中使用配置文件：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">public UnitTest1()
{
    var builder = new ConfigurationBuilder()
        .AddJsonFile(&quot;appsettings.json&quot;);
    var configuration = builder.Build();
    var settings = configuration.GetSection(&quot;RedisSettings&quot;).Get&lt;RedisSettings&gt;();
    _mock.Setup(p =&gt; p.Value).Returns(settings);
}
</code></pre>
<h1 id="自定义-ConfigProvider：对数据库连接字符串等敏感信息进行加密"><a href="#自定义-ConfigProvider：对数据库连接字符串等敏感信息进行加密" class="headerlink" title="自定义 ConfigProvider：对数据库连接字符串等敏感信息进行加密"></a>自定义 ConfigProvider：对数据库连接字符串等敏感信息进行加密</h1><p>Startup.cs</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">public Startup(IWebHostEnvironment env)
{
    var builder = new ConfigurationBuilder()
      .SetBasePath(env.ContentRootPath)
      .AddJsonFile(&quot;appsettings.json&quot;, optional: false, reloadOnChange: true)
      .AddJsonFile($&quot;appsettings.{env.EnvironmentName}.json&quot;, optional: true)
      .AddEncryptedProvider($&quot;appsettings.{env.EnvironmentName}.json&quot;)
      .AddEnvironmentVariables();
    Configuration = builder.Build();
}
</code></pre>
<p>AddEncryptedProvider 扩展方法</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">using Microsoft.Extensions.Configuration;

    public static class CustomConfigProviderExtensions
    {
        public static IConfigurationBuilder AddEncryptedProvider(this IConfigurationBuilder builder, string path)
        {
            return builder.Add(new CustomConfigProvider(path));
        }
    }
</code></pre>
<p>CustomConfigProvider.cs</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">using Microsoft.Extensions.Configuration;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;


    public class CustomConfigProvider : ConfigurationProvider, IConfigurationSource
    {
        private string JsonFilePath { get; }
        private const string EncryptKey = &quot;your encryptedKEY&quot;;

        public CustomConfigProvider()
        {

        }

        public CustomConfigProvider(string path)
        {
            JsonFilePath = path;
        }

        public override void Load()
        {
            Data = UnencryptMyConfiguration();
        }

        private IDictionary&lt;string, string&gt; UnencryptMyConfiguration()
        {
            var configValues = new Dictionary&lt;string, string&gt;();
            if (!File.Exists(JsonFilePath))
                return configValues;
            var jsonRoot = JObject.Parse(File.ReadAllText(JsonFilePath));

            var key = &quot;ConnectionStrings&quot;;
            var jObject = jsonRoot.GetValue(key);
            foreach (var x in jObject.Children())
            {
                var hasChild = ((JContainer)x).First.HasValues;
                if (hasChild)
                {
                    var i = 0;
                    foreach (var y in ((JArray)((JContainer)x).First).Children())
                    {
                        configValues.Add($&quot;{ key}:{((JProperty)x).Name}:{i++}&quot;, AesDecrypt(((JValue)y).Value.ToString(),EncryptKey));
                    }
                }
                //
                else
                {
                    configValues.Add($&quot;{ key}:{((JProperty)x).Name}&quot;, AesDecrypt(((JValue)((JProperty)x).First).Value.ToString(),EncryptKey));
                }
            }
            return configValues;
        }

        public IDictionary&lt;string, string&gt; CreateAndSaveDefaultValues(IDictionary&lt;string, string&gt; defaultDictionary = null)
        {
            var configValues = new Dictionary&lt;string, string&gt;();
            if (defaultDictionary == null)
            {
                if (!File.Exists(JsonFilePath))
                    return configValues;
                var jsonRoot = JObject.Parse(File.ReadAllText(JsonFilePath));

                var jObject = jsonRoot.GetValue(&quot;ConnectionStrings&quot;);
                foreach (var x in jObject.Children())
                {
                    var encryptValue = AesEncrypt(((JValue)((JProperty)x).First).Value.ToString(), EncryptKey);
                    configValues.Add(((JProperty)x).Name, encryptValue);
                }
            }
            else
            {
                foreach (var x in defaultDictionary)
                {
                    configValues.Add(x.Key, AesEncrypt(x.Value, EncryptKey));
                }
            }
            return configValues;
        }
        public IConfigurationProvider Build(IConfigurationBuilder builder)
        {
            return new CustomConfigProvider(JsonFilePath);
        }

        public string Decrypt(string str)
        {
            return AesDecrypt(str, EncryptKey);
        }
        public string Encrypt(string str)
        {
            return AesEncrypt(str, EncryptKey);
        }

        private string AesEncrypt(string str, string key)
        {
            if (string.IsNullOrEmpty(str)) return null;
            var toEncryptArray = Encoding.UTF8.GetBytes(str);

            var rm = new RijndaelManaged
            {
                Key = Encoding.UTF8.GetBytes(key),
                Mode = CipherMode.ECB,
                Padding = PaddingMode.PKCS7
            };

            var cTransform = rm.CreateEncryptor();
            var resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            return Convert.ToBase64String(resultArray);
        }
        private string AesDecrypt(string str, string key)
        {
            if (string.IsNullOrEmpty(str)) return null;
            var toEncryptArray = Convert.FromBase64String(str);

            var rm = new RijndaelManaged
            {
                Key = Encoding.UTF8.GetBytes(key),
                Mode = CipherMode.ECB,
                Padding = PaddingMode.PKCS7
            };

            var cTransform = rm.CreateDecryptor();
            var resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return Encoding.UTF8.GetString(resultArray);
        }
    }
</code></pre>
<h1 id="一个官方例子"><a href="#一个官方例子" class="headerlink" title="一个官方例子"></a>一个官方例子</h1><blockquote>
<p><a href="https://docs.microsoft.com/zh-cn/aspnet/core/security/app-secrets?view=aspnetcore-2.2&amp;tabs=windows" target="_blank" rel="noopener">https://docs.microsoft.com/zh-cn/aspnet/core/security/app-secrets?view=aspnetcore-2.2&amp;tabs=windows</a></p>
</blockquote>
<p></p><p class="code-caption" data-lang="json" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="json">{
  &quot;Movies&quot;: {
    &quot;ServiceApiKey&quot;: &quot;12345&quot;,
    &quot;ConnectionString&quot;: &quot;Server=(localdb)\\mssqllocaldb;Database=Movie-1;Trusted_Connection=True;MultipleActiveResultSets=true&quot;
  }
}
</code></pre>
<p>配置模型：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">public class MovieSettings
{
    public string ConnectionString { get; set; }

    public string ServiceApiKey { get; set; }
}

//使用
var moviesConfig = Configuration.GetSection(&quot;Movies&quot;).Get&lt;MovieSettings&gt;();
_moviesApiKey = moviesConfig.ServiceApiKey;
</code></pre>
<h1 id="NET-6-下使用-Configuration"><a href="#NET-6-下使用-Configuration" class="headerlink" title=".NET 6 下使用 Configuration"></a>.NET 6 下使用 Configuration</h1><p>JSON 文件：</p>
<p></p><p class="code-caption" data-lang="json" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="json">{
  &quot;DockItemOptions&quot;: {
    &quot;ProductGroups&quot;: {
      &quot;GroupA&quot;: [
        {
          &quot;Id&quot;: &quot;A_1&quot;,
          &quot;Name&quot;: &quot;na_1&quot;
        },
        {
          &quot;Id&quot;: &quot;A_2&quot;,
          &quot;Name&quot;: &quot;na_2&quot;
        }
      ],
      &quot;GroupB&quot;: [
        {
          &quot;Id&quot;: &quot;B_1&quot;,
          &quot;Name&quot;: &quot;nb_1&quot;
        },
        {
          &quot;Id&quot;: &quot;B_2&quot;,
          &quot;Name&quot;: &quot;nb_2&quot;
        }
      ]
    }
  }
}
</code></pre>
<p>Program.cs 中设置</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">using System.Text.Encodings.Web;
using Weather.Web;
using Weather.Web.Models;
using Microsoft.Extensions.DependencyInjection;

IConfiguration configuration = new ConfigurationBuilder()
    .AddJsonFile(&quot;appsettings.json&quot;)
    .Build();

var builder = WebApplication.CreateBuilder(args);

// other codes ...

builder.Services.Configure&lt;DockItemOptions&gt;(configuration.GetSection(DockItemOptions.SettingsKey));

var app = builder
    .Build();
// other codes ...
</code></pre>
<p>Controller 中调用：</p>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Weather.Web.Models;

namespace Weather.Web.Controllers
{
    [ApiController]
    [Route(&quot;[controller]&quot;)]
    public class WeatherController : ControllerBase
    {
        private readonly DockItemOptions _dockItemOptions;
        public WeatherController(IOptions&lt;DockItemOptions&gt; dockOptions)
        {
            _dockItemOptions = dockOptions.Value;
        }

        [HttpGet(&quot;Test&quot;)]
        public async Task&lt;string&gt; Test()
        {
            _dockItemOptions.ProductGroups.TryGetValue(&quot;GroupA&quot;, out var items);
            return items.Count;
        }
    }
}
</code></pre>
<p>models：</p>
<blockquote>
<p>注意事项见注释部分</p>
</blockquote>
<p></p><p class="code-caption" data-lang="csharp" data-line_number="backend" data-trim_indent="backend" data-label_position="outer" data-labels_left="Code" data-labels_right=":" data-labels_copy="Copy Code"><span class="code-caption-label"></span></p><p></p>
<pre><code class="csharp">using Newtonsoft.Json;

namespace Weather.Web.Models
{
    public class DockItemOptions
    {
        public const string SettingsKey = &quot;DockItemOptions&quot;;

        [JsonProperty(&quot;ProductGroups&quot;)]
        public Dictionary&lt;string, List&lt;DockItem&gt;&gt; ProductGroups { get; set; } = new Dictionary&lt;string, List&lt;DockItem&gt;&gt;(); //务必注意：这里一定要有 get 和 set，否则 configuration.GetSection 的 value 会一直为 null
    }

    public class DockItem
    {
        public string Id { get; set; }

        public string Name { get; set; }
    }
}
</code></pre>
<h1 id="FAQ"><a href="#FAQ" class="headerlink" title="FAQ"></a>FAQ</h1><ol>
<li>在使用AddJsonFile的时候，被添加的json文件需要在项目所处根目录内，否则不会加载（路径默认是到项目文件夹，而非bin目录下）。打包发布后会自动从发布文件夹找对应的配置文件<ul>
<li>这里主要是为了应对新建了一个项目A，然后在这个项目A中添加了一个配置文件config.json，项目B引用这个项目A后，虽然最终编译之后会在bin文件夹内自动生成config.json，但是在调试模式下，默认的路径是在项目路径，而非bin下的文件夹路径，这会导致config.json在开发模式下（调试时）不会被加载。<ul>
<li>可以手动将改config.json文件复制一份到项目B根目录内。</li>
<li>如果是用nuget发布项目A后，项目B再从nuget安装项目A，则不会有此问题。</li>
</ul>
</li>
</ul>
</li>
</ol>

      

      <div>
        
        <div style="background-color: rgb(255, 23, 0);user-select: auto;height: 3px;width:100%;margin-top: 40px;margin-bottom:15px;"></div>

<!-- <p>常言道：学然后知不足，教然后知困。</p>
<p>我知道你的焦虑，一起共进加油：P</p>
<p>关不关注都无所谓，会根据生活节奏紧凑度定期分享些开发经验、搬砖生涯、痛点、感悟。</p>
<p>
        <img src="https://pic.zhuliang.ltd/20191213133908.gif" alt="欢迎关注我的订阅号：P" />
</p> -->
<ul class="post-copyright" style="margin-left:0px;">
    <li class="post-copyright-author">
        <strong>本文作者：</strong>积慕
    </li>
    <li class="post-copyright-link">
        <strong>本文链接：</strong>
        <a href="/2019/02/backend/configurationBuilder-in-netCore.html" title="在.net core中使用配置文件的几个示例和方法">https://blog.zhuliang.ltd/2019/02/backend/configurationBuilder-in-netCore.html</a>
    </li>
    <li class="post-copyright-license">
        <strong>版权： </strong>
        本站文章均采用 <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/cn/" rel="external nofollow"
            target="_blank">CC BY-NC-SA 3.0 CN</a> 许可协议，请勿用于商业，转载注明出处！
    </li>
</ul>
        
      </div>
    </div>

    <footer>
      
      
  
  <div class="categories">
    <a href="/categories/backend/">backend</a>
  </div>

      
  
  <div class="tags">
    <a href="/tags/教程/">教程</a>, <a href="/tags/net-core/">.net core</a>
  </div>

      <!-- 
  <div class="addthis addthis_toolbox addthis_default_style">
    
    
      <a class="addthis_button_tweet"></a>
    
    
      <a class="addthis_button_google_plusone" g:plusone:size="medium"></a>
    
    
      <a class="addthis_button_pinterest_pinit" pi:pinit:layout="horizontal"></a>
    
    <a class="addthis_counter addthis_pill_style"></a>
  </div>
  <script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js"></script>
 -->
      
      <div class="clearfix"></div>
    </footer>
  </div>
</article>

<!-- 
<section id="comment">
  <h1 class="title">留言</h1>

  <div id="vcomments" style="background-color: #fff"></div>
  <script>
    new Valine({
      el: '#vcomments',
      appId: 'aTPKmG6tjDo3CbIXzAPzrj4X-gzGzoHsz',
      appKey: 'hNgWFneNpEcMnBJclPQnDgsd',
      notify: true,
      verify: true, //验证码
      avatar: 'monsterid', //https://valine.js.org/avatar.html
      placeholder: '请输入你的评论'
    })
  </script>
</section>
 --> <!--启用/关闭 LeanCloud 评论--></div></div>
    <aside id="sidebar" class="alignright">
  
<div class="widget tag">
  <h3 class="title"><i class="iconfont icon-category"></i>&nbsp;&nbsp;分类</h3>
  <ul class="entry">
  
    <li><a href="/categories/Obsidian/">Obsidian</a><small>1</small></li>
  
    <li><a href="/categories/PowerUser/">PowerUser</a><small>4</small></li>
  
    <li><a href="/categories/backend/">backend</a><small>57</small></li>
  
    <li><a href="/categories/frontend/">frontend</a><small>9</small></li>
  
    <li><a href="/categories/operations/">operations</a><small>5</small></li>
  
    <li><a href="/categories/提前退休/">提前退休</a><small>2</small></li>
  
  </ul>
</div>


  
<div class="widget tag">
  <h3 class="title"><i class="iconfont icon-new3"></i>&nbsp;&nbsp;最新文章</h3>
  <ul class="entry">
    
      <li>
        <a href="/2024/11/PowerUser/install-docker-in-pve-lxc.html">1. 通过 PVE LXC 搭建 docker 环境</a>
      </li>
    
      <li>
        <a href="/2024/11/Obsidian/obsidian-render-pie-chart.html">2. 2 套用于 obsidian 的生成时间占用饼图脚本示例，基于 templater， charts，echarts+dataview</a>
      </li>
    
      <li>
        <a href="/2024/10/PowerUser/fix-ios18-samba-readonly-issue.html">3. 解决 ios 18（包括ipadOS 18） 下通过文件(files app)连接 samba 服务器，目录变成只读权限的问题</a>
      </li>
    
      <li>
        <a href="/2023/07/operations/how-to-use-pm2.html">4. PM2 的安装、配置和使用</a>
      </li>
    
      <li>
        <a href="/2023/07/backend/expose-intranet-netcoreapi-to-internet.html">5. 通过 DDNS+显性URL 把内网部署的.NET CORE WEBAPI 项目暴露到公网中</a>
      </li>
    
  </ul>
</div>


  
<div class="widget tag">
  <h3 class="title"><i class="iconfont icon-tag"></i>&nbsp;&nbsp;标签</h3>
  <ul class="entry">
  
    <li><a href="/tags/net-core/">.net core</a><small>12</small></li>
  
    <li><a href="/tags/Debian/">Debian</a><small>2</small></li>
  
    <li><a href="/tags/Docker/">Docker</a><small>1</small></li>
  
    <li><a href="/tags/Elasticsearch/">Elasticsearch</a><small>35</small></li>
  
    <li><a href="/tags/Elasticsearch-Nest系列/">Elasticsearch.Nest系列</a><small>35</small></li>
  
    <li><a href="/tags/Obsidian/">Obsidian</a><small>1</small></li>
  
    <li><a href="/tags/PVE/">PVE</a><small>2</small></li>
  
    <li><a href="/tags/StackExchange-Redis系列/">StackExchange.Redis系列</a><small>12</small></li>
  
    <li><a href="/tags/centos/">centos</a><small>3</small></li>
  
    <li><a href="/tags/flex/">flex</a><small>1</small></li>
  
    <li><a href="/tags/ios/">ios</a><small>1</small></li>
  
    <li><a href="/tags/javascript/">javascript</a><small>1</small></li>
  
    <li><a href="/tags/linux/">linux</a><small>4</small></li>
  
    <li><a href="/tags/nginx/">nginx</a><small>2</small></li>
  
    <li><a href="/tags/nuget/">nuget</a><small>2</small></li>
  
    <li><a href="/tags/react/">react</a><small>6</small></li>
  
    <li><a href="/tags/styled-components/">styled-components</a><small>1</small></li>
  
    <li><a href="/tags/内网穿透/">内网穿透</a><small>4</small></li>
  
    <li><a href="/tags/培训讲义/">培训讲义</a><small>2</small></li>
  
    <li><a href="/tags/基础知识/">基础知识</a><small>2</small></li>
  
    <li><a href="/tags/性能优化/">性能优化</a><small>2</small></li>
  
    <li><a href="/tags/教程/">教程</a><small>64</small></li>
  
    <li><a href="/tags/理财/">理财</a><small>2</small></li>
  
    <li><a href="/tags/生命周期/">生命周期</a><small>1</small></li>
  
    <li><a href="/tags/经验/">经验</a><small>4</small></li>
  
  </ul>
</div>


  
  <script type="text/javascript" charset="utf-8" src="/js/tagcloud.js"></script>
  <script type="text/javascript" charset="utf-8" src="/js/tagcanvas.js"></script>
  <div class="widget tag">
    <h3 class="title"><i class="iconfont icon-cloud1"></i>&nbsp;&nbsp;标签云</h3>
    <div id="myCanvasContainer" class="widget tagcloud">
      <canvas width="250" height="250" id="resCanvas" style="width:100%">
        <a href="/tags/net-core/" style="font-size: 17.14px;">.net core</a> <a href="/tags/Debian/" style="font-size: 11.43px;">Debian</a> <a href="/tags/Docker/" style="font-size: 10px;">Docker</a> <a href="/tags/Elasticsearch/" style="font-size: 18.57px;">Elasticsearch</a> <a href="/tags/Elasticsearch-Nest系列/" style="font-size: 18.57px;">Elasticsearch.Nest系列</a> <a href="/tags/Obsidian/" style="font-size: 10px;">Obsidian</a> <a href="/tags/PVE/" style="font-size: 11.43px;">PVE</a> <a href="/tags/StackExchange-Redis系列/" style="font-size: 17.14px;">StackExchange.Redis系列</a> <a href="/tags/centos/" style="font-size: 12.86px;">centos</a> <a href="/tags/flex/" style="font-size: 10px;">flex</a> <a href="/tags/ios/" style="font-size: 10px;">ios</a> <a href="/tags/javascript/" style="font-size: 10px;">javascript</a> <a href="/tags/linux/" style="font-size: 14.29px;">linux</a> <a href="/tags/nginx/" style="font-size: 11.43px;">nginx</a> <a href="/tags/nuget/" style="font-size: 11.43px;">nuget</a> <a href="/tags/react/" style="font-size: 15.71px;">react</a> <a href="/tags/styled-components/" style="font-size: 10px;">styled-components</a> <a href="/tags/内网穿透/" style="font-size: 14.29px;">内网穿透</a> <a href="/tags/培训讲义/" style="font-size: 11.43px;">培训讲义</a> <a href="/tags/基础知识/" style="font-size: 11.43px;">基础知识</a> <a href="/tags/性能优化/" style="font-size: 11.43px;">性能优化</a> <a href="/tags/教程/" style="font-size: 20px;">教程</a> <a href="/tags/理财/" style="font-size: 11.43px;">理财</a> <a href="/tags/生命周期/" style="font-size: 10px;">生命周期</a> <a href="/tags/经验/" style="font-size: 14.29px;">经验</a>
      </canvas>
    </div>
  </div>




</aside>
    <div class="clearfix"></div>
  </div>
  <footer id="footer" class="inner"><div class="alignleft">

  
  &copy; 2018 - 2024 &nbsp;<a href='/about'>积慕</a>
  
  &nbsp;&nbsp;<a href='https://www.cnblogs.com/deepthought/'>我的博客园地址</a>
  &nbsp;&nbsp;finalclassic#outlook.com
</div>

<div class="clearfix"></div>
<div>
  本站主题基于：<a href='https://github.com/hexojs/hexo-theme-light' rel="external nofollow">hexo-theme-light</a>
</div>
<div id="busuanzi_container_site_pv">
  本站总访问量&nbsp;<span id="busuanzi_value_site_pv"></span>&nbsp;次
</div>
<div style="width:300px;margin:0 auto; padding:20px 0;">
  <a target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=31011702004805" style="display:inline-block;text-decoration:none;height:20px;line-height:20px;">
    <img src="https://pic.zhuliang.ltd/20200102164648.png" style="float:left;"><p style="float:left;height:20px;line-height:20px;margin: 0px 0px 0px 5px; color:#939393;">沪公网安备 31011702004805号</p></a>
</div></footer>
  <script src="/js/jquery-2.0.3.min.js"></script>
<script src="/js/jquery.imagesloaded.min.js"></script>
<script src="/js/gallery.js"></script>




<link rel="stylesheet" href="/fancybox/jquery.fancybox.css" media="screen" type="text/css">
<script src="/fancybox/jquery.fancybox.pack.js"></script>
<script type="text/javascript">
(function($){
  $('.fancybox').fancybox();
})(jQuery);
</script>


<script type="text/javascript">
hljs.initHighlightingOnLoad();
</script>

<!-- <script src="/js/busuanzi.pure.mini.js"></script> -->
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<script>
    var _hmt = _hmt || [];
    (function () {
        var hm = document.createElement("script");
        hm.src = "https://hm.baidu.com/hm.js?ea793b9c8d6b31df666a6bc15038e246";
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(hm, s);
    })();
</script>
<script>
    (function () {
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        }
        else {
            bp.src = 'http://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>
</body>
</html>
